/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package unc.pds.auth;

import java.rmi.RemoteException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.ejb.FinderException;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import unc.pds.data.Consts;
import unc.pds.data.KeyGen;
import unc.pds.exc.NotEnoughDataException;
import unc.pds.exc.PDSSecurityException;
import unc.pds.exc.UserAlreadyExistException;
import unc.pds.model.ModelFactory;
import unc.pds.model.UserRemote;
import unc.pds.util.Arch;

/**
 *
 * @author ain
 */
public class SecStupidImpl implements IPDSSecurity {

    private Long sessionKey;
    private UserRemote curUser = null;

    public SecStupidImpl(Long nseskey){
        sessionKey = nseskey;
    }

    public boolean getCrPermission(Long objkey, String entity) throws RemoteException {
        return true;
    }

    public boolean getPermission(Long objkey, String act) throws RemoteException {
        return true;
    }

    public boolean getPermission(Long objkey, String field, String act) throws RemoteException {
        return true;
    }

    public boolean setPermission(Long objkey, String entity, String act, String level) throws RemoteException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    private Connection getConnection() throws NamingException, SQLException {
        DataSource ds = (DataSource) (new InitialContext()).lookup("oracle/SOS");
        return ds.getConnection();
    }

    public Long login(String nick, String password) throws RemoteException {
        try {
            Long object_type_id = getObjectTypeID(Consts.OBJECT_TYPE__USER);
            Long pass_attr_id = getAttributeID(Consts.ATTR__USER_PASSWORD, object_type_id);
            Long nick_attr_id = getAttributeID(Consts.ATTR__USER_NICKNAME, object_type_id);
            Connection conn = getConnection();
            ResultSet ans = null;
            Statement query = null;
            try {
                query = conn.createStatement();
                String sqlquerry = "SELECT * FROM PARAMS WHERE "
                        + Consts.PARAMS__ATTRIBUTE_ID + "=" + pass_attr_id + " AND "
                        + Consts.PARAMS__VALUE + "='" + password + "' AND "
                        + Consts.PARAMS__OBJECT_ID + " IN ("
                        + "SELECT " + Consts.PARAMS__OBJECT_ID + " FROM PARAMS WHERE "
                        + Consts.PARAMS__ATTRIBUTE_ID + "=" + nick_attr_id + " AND "
                        + Consts.PARAMS__VALUE + "='" + nick + "')";
                ans = query.executeQuery(sqlquerry);
                if (ans.next()) {
                    sessionKey = new Long(ans.getLong(Consts.PARAMS__OBJECT_ID));
                    return sessionKey;
                } else {
                    return null;
                }
            } finally {
                ans.close();
                query.close();
                conn.close();
            }
        } catch (Exception e) {
            throw new RemoteException(e.toString());
        }
    }

    public Long register(Arch doc) throws RemoteException, PDSSecurityException {
        if ((doc.getChild(Consts.ATTR__USER_NICKNAME) == null) || (doc.getChild(Consts.ATTR__USER_PASSWORD) == null)) {
            throw new NotEnoughDataException();
        }
        String nickname = doc.getChild(Consts.ATTR__USER_NICKNAME).getValue();
        if (userExist(nickname)) {
            throw new UserAlreadyExistException();

        }
        String type = Consts.OBJECT_TYPE__USER;
        Long object_type_id = getObjectTypeID(Consts.OBJECT_TYPE__USER);
        Long object_id = KeyGen.getInstance().getKey();
        //добавляем запись юзера в таблицу объектов
        try {
            Connection conn = getConnection();
            Statement query = null;
            try {
                String names = Consts.OBJECTS__OBJECT_ID + ","
                        + Consts.OBJECTS__OBJECT_TYPE_ID + ","
                        + Consts.OBJECTS__NAME;
                String values = ") VALUES ("
                        + object_id + "," + object_type_id + ",'" + nickname + "'";
                query = conn.createStatement();
                String endquerry = "INSERT INTO OBJECTS ("
                        + names
                        + values + ")";
                if (Consts.DEBUG_MODE) System.out.println(endquerry);
                if (query.executeUpdate(endquerry) == 0) {
                    throw new RemoteException("cannot create user: insert return 0");

                }
            } finally {
                query.close();
                conn.close();
            }
        } catch (Exception ex) {
            if (Consts.DEBUG_MODE) System.out.println("SecB.register: " + ex.getLocalizedMessage());
            throw new RemoteException("SecB.register: " + ex.getLocalizedMessage());
        }
        //заполняем поля в PARAMS
        try {
            for (int i = 0; i < doc.getChilds().length; i++) {
                Arch child = doc.getChilds()[i];
                if ((child.getName().compareTo(Consts.ARCH_F_NAME) != 0)
                        && (child.getName().compareTo(Consts.ARCH_F_PARENT) != 0)
                        && (child.getName().compareTo(Consts.ARCH_F_TYPE) != 0)) {
                    //addParameter(child.getName(), child.getValue());
                    try {
                        Long attr_id = getAttributeID(child.getName(), object_type_id);
                        Connection conn = getConnection();
                        ResultSet ans = null;
                        Statement query = null;
                        try {
                            query = conn.createStatement();
                            ans = query.executeQuery("INSERT INTO PARAMS ("
                                    + Consts.PARAMS__OBJECT_ID + ","
                                    + Consts.PARAMS__ATTRIBUTE_ID + ","
                                    + Consts.PARAMS__VALUE + ") VALUES ("
                                    + object_id + ","
                                    + attr_id + ",'"
                                    + child.getValue() + "')");
                        } finally {
                            ans.close();
                            query.close();
                            conn.close();
                        }
                    } catch (Exception ex) {
                        if (Consts.DEBUG_MODE) System.out.println("SecB.addUserParameter: " + ex.getLocalizedMessage());
                        throw new Exception("SecB.addUserParameter: " + ex.getLocalizedMessage());
                    }
                }
            }
        } catch (Exception ex) {
            if (Consts.DEBUG_MODE) System.out.println("SecB.register: " + ex.getLocalizedMessage());
            throw new RemoteException("SecB.register: " + ex.getLocalizedMessage());
        }
        sessionKey = object_id;
        return sessionKey;
    }

    private boolean userExist(String nickname) throws RemoteException {
        try {
            Long object_type_id = getObjectTypeID(Consts.OBJECT_TYPE__USER);
            Long nick_attr_id = getAttributeID(Consts.ATTR__USER_NICKNAME, object_type_id);
            Connection conn = getConnection();
            ResultSet ans = null;
            Statement query = null;
            try {
                query = conn.createStatement();
                String sqlquerry = "SELECT * FROM PARAMS WHERE "
                        + Consts.PARAMS__ATTRIBUTE_ID + "=" + nick_attr_id + " AND "
                        + Consts.PARAMS__VALUE + "='" + nickname + "'";
                ans = query.executeQuery(sqlquerry);
                if (ans.next()) {
                    return true;
                } else {
                    return false;
                }
            } finally {
                ans.close();
                query.close();
                conn.close();
            }
        } catch (Exception e) {
            throw new RemoteException(e.toString());
        }
    }

    private Long getObjectTypeID(String name) throws RemoteException {
        {
            try {
                Connection conn = getConnection();
                ResultSet ans = null;
                Statement query = null;
                try {
                    query = conn.createStatement();
                    ans = query.executeQuery("SELECT * FROM OBJECT_TYPES "
                            + "WHERE NAME='" + name + "'");
                    if (ans.next()) {
                        return new Long(ans.getLong(Consts.OBJECT_TYPES__ID));
                    } else {
                        throw new RemoteException("SecB.getObjTypeID: not such object_type " + name);
                    }
                } finally {
                    ans.close();
                    query.close();
                    conn.close();
                }
            } catch (Exception e) {
                throw new RemoteException("SecB.getObjTypeID: " + e.getLocalizedMessage());
            }
        }
    }

    private Long getAttributeID(String name, Long object_type_id) throws FinderException, RemoteException {

        try {
            Connection conn = getConnection();
            ResultSet ans = null;
            Statement query = null;
            try {
                query = conn.createStatement();
                ans = query.executeQuery("SELECT * FROM ATTRIBUTES "
                        + "WHERE OBJECT_TYPE_ID='" + object_type_id + "' AND "
                        + "NAME='" + name + "'");
                if (ans.next()) {
                    return new Long(ans.getLong(Consts.ATTRIBUTES__ATTRIBUTE_ID));
                } else {
                    throw new FinderException("SecB.getAttrID: not attr_id for " + name);
                }
            } finally {
                ans.close();
                query.close();
                conn.close();
            }
        } catch (Exception e) {
            throw new RemoteException("SecB.getAttr_id: " + e.toString());
        }
    }

    public UserRemote getCurrentUser() throws RemoteException {
        if (sessionKey.compareTo(SecurityST.LoginSessionKey) == 0) {
            //логин насяника
            curUser = null;
        } else {
            if (curUser == null) {
                curUser = (UserRemote) ModelFactory.getByKey(sessionKey, sessionKey);
            }
        }
        return curUser;
    }

    public boolean setPermission(Long objkey, Long userkey, String entity, String field, String act, boolean access) throws RemoteException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public boolean dropAllPermission(Long user, Long dropfor) throws RemoteException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public boolean dropPermission(Long entityKey, Long dropfor, String entity, String field, String act) throws RemoteException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public boolean dropPermission(Long entityKey, String entity, String field, String act) throws RemoteException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void setProtectOn(Long entityKey) throws RemoteException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public boolean getPermission(Long objkey, String entity, String field, String act) throws RemoteException {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}
